﻿using System;
using System.Collections.Generic;
using System.Text;
using WsProtocol.IEC62056.DataTypeClass;
using Comm.PublicClass;

namespace WsProtocol.IEC62056.CosemACSE
{
    // hxh 2018-5 62056 实现操作服务原语的所有类
    public class ActionNormal 
    {
        public static string Request(CosemObject OI, ref string errorinfo)
        {
            try
            {
                string FormatValue = string.Empty;
                FormatValue = CAD.GetFormatValue(OI, ref errorinfo);

                if (OI.DataNode == null) return FormatValue + "00";//无数据

                if (string.IsNullOrEmpty(OI.DataNode.SetValue) && OI.DataNode.eleNodeList.Count == 0)
                {
                    return FormatValue + "00";//无数据
                }
                else
                {
                    string Datastr = Data.GetFormatValue(OI.DataNode, ref errorinfo);
                    return FormatValue + "01" + Datastr;
                }
            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                return string.Empty;
            }

        }

        public static int Response(ref string frameData, CosemObject OI,  ref string errorinfo)
        {
            int iResult = 0;
            iResult = SetNormal.Response(ref frameData, OI, ref errorinfo);
            if (iResult < 0) return iResult;

            //操作响应可能有附加数据返回
            string resultflag = frameData.Substring(0, 2);
            frameData = frameData.Remove(0, 2);
            if (MyConvert.getInt32(resultflag) == 0)// 表示有无Get-Data-Result数据
            {
                iResult = 0;
            }
            else //有Get-Data-Result
            {
                int GetDR = MyConvert.getInt32(frameData.Substring(0, 2));
                frameData = frameData.Remove(0, 2);
                if (GetDR == (int)GetResult.data)
                    iResult = Data.AnalizeData(ref frameData, OI.DataNode, ref errorinfo);//DATA (Optional)
                else if (GetDR == (int)GetResult.AccessResult)
                {
                    OI.DataNode.ReadValue = ((DAR)int.Parse(frameData.Substring(0, 2))).ToString();
                }
            }
            return iResult;
        }

        public static int AnalizeAppendData(ref string frameData, ElementData eleNode, int count,ref string errorinfo) {
            int iresult = 0;
            int i = 1;
            ElementData tmpNode = null;
            while (frameData != "") {
                ElementData tmpNodeChild = null;
                if (eleNode.eleNodeList.Count == 0)
                    tmpNodeChild = eleNode;
                else
                {
                    if (count == 0 && i > eleNode.eleNodeList.Count)
                    {
                        tmpNode = (ElementData)eleNode.eleNodeList[0].DeepClone();//先客隆一个
                        tmpNode.CAD = tmpNode.SetValue = tmpNode.InputValue = "";
                        eleNode.eleNodeList.Add(tmpNode);
                    }
                    else if (i > eleNode.eleNodeList.Count)
                        break;

                    tmpNodeChild = eleNode.eleNodeList[i - 1];
                }
                if (tmpNodeChild.eleNodeList.Count > 0)
                {
                    iresult = AnalizeAppendData(ref frameData, tmpNodeChild,tmpNodeChild.eleNodeList.Count, ref errorinfo);
                }
                else {
                    enumData dtype = (enumData)Enum.Parse(typeof(enumData), tmpNodeChild.DataType);
                    switch (dtype) { 
                        case enumData.octet_string:
                        case enumData.visible_string:
                        case enumData.utf8_string:
                            iresult = octString.AnalizeDataSpecial(ref frameData, tmpNodeChild, ref errorinfo);
                            break;
                        //case enumData.BCD:
                        //    iresult = BCD.AnalizeData(ref frameData, tmpNodeChild, ref errorinfo);
                        //    break;
                        //case enumData.BCDYYMMDDHHmm:
                        //    iresult = BCDYYMMDDHHmm.AnalizeData(ref frameData, tmpNodeChild, ref errorinfo);
                        //    break;
                        default:
                            iresult = Data.AnalizeData(ref frameData, tmpNodeChild, ref errorinfo);
                            break;
                    }
                }
                i++;
            }
            return 0;
        }
    }

    public class ActionNextPblock 
    {
        public static string Request(double frameseq)
        {
            return MyConvert.DecToHex(frameseq.ToString(), 4 * 2); //Unsigned32 4字节           
        }

        public static int Response(ref string frameData, ref long frameseq, ref string errorinfo)
        {
            int iResult = -1;
            if (string.IsNullOrEmpty(frameData))
            {
                errorinfo = "解析数据为空";
                return iResult;
            }
            try
            {
                frameseq = Convert.ToInt32(frameData.Substring(0, 8), 16);//帧序号               
                frameData = frameData.Remove(0, 8);
            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                iResult = -1;
            }
            return iResult;
        }
    }

    public class ActionList 
    {
        public static string Request(List<CosemObject> OIList, ref string errorinfo)
        {
            string FormatValue = string.Empty;

            int eleNum = OIList.Count;
            string sData = string.Empty;
            foreach (CosemObject OI in OIList)
            {
                FormatValue = FormatValue + CAD.GetFormatValue(OI,ref errorinfo);
                sData += Data.GetFormatValue(OI.DataNode,ref errorinfo);
            }

            return BERiLen.GetFormatValue(eleNum) + FormatValue + BERiLen.GetFormatValue(eleNum) + sData;
        }

        public static int Response(ref string frameData, List<CosemObject> OIList, ref string errorinfo)
        {
            int iResult = -1;
            if (string.IsNullOrEmpty(frameData))
            {
                errorinfo = "解析数据为空！";
                return iResult;
            }
            try
            {
                int DNum = BERiLen.AnalizeData(ref frameData, ref errorinfo);
                for (int i = 0; i < DNum; i++)
                {
                    if (i > OIList.Count - 1)
                        OIList.Add(new CosemObject());
                    iResult = ActionNormal.Response(ref frameData, OIList[i], ref errorinfo);
                }
            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                iResult = -1;
            }
            return iResult;      

        }
    }

    public class ActionFirstPblock : SetFirstOrLastDatablock
    {
        public static string Request(CosemObject OI, ref string errorinfo)
        {
            string FormatValue = string.Empty;
            try
            {
                FormatValue = CAD.GetFormatValue(OI, ref errorinfo);

                FormatValue += DataBlockSA.GetFormatValue(OI.DataNode, ref errorinfo);
            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();

            }
            return FormatValue;
        }

        public static string Request(CosemObject OI, ref string BlockData, int DataLen, ref string errorinfo)
        {
            string FormatValue = string.Empty;
            try
            {
                FormatValue = CAD.GetFormatValue(OI, ref errorinfo);

                int SDataLen = DataLen - FormatValue.Length;
                FormatValue += DataBlockSA.GetFormatValue(BlockData, ref SDataLen,1,ref errorinfo);
                BlockData = BlockData.Substring(SDataLen);

                //string mblockData = BlockData.Substring(0, DataLen * 2 - FormatValue.Length);

                //FormatValue += DataBlockSA.GetFormatValue(mblockData, 1, false, ref errorinfo);
                //BlockData = BlockData.Substring(mblockData.Length);

            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
            }
            return FormatValue;
        }

        //public static int Response(ref string frameData, List<CosemObject> OIList,ref string errorinfo)
        //{
        //    int iResult = -1;
        //    if (string.IsNullOrEmpty(frameData))
        //    {
        //        errorinfo = "解析数据为空";
        //        return iResult;
        //    }
        //    try
        //    {
        //        int eleNum = Convert.ToInt32(frameData.Substring(0, 2), 16);
        //        frameData = frameData.Remove(0, 2);

        //        CosemObject OI = null;
        //        CosemObject lastOI = OIList[OIList.Count - 1];
        //        for (int i = 0; i < eleNum; i++)
        //        {
        //            if (i >= OIList.Count)
        //            {
        //                OI = (CosemObject)lastOI.DeepClone();//.Clone(); //如果数据格式不够，按最后一个OI克隆一个

        //                OIList.Add(OI);
        //            }
        //            else
        //                OI = OIList[i];

        //          //  iResult = ActionThenGet.Response(ref frameData, OI, obEncryption, ref errorinfo);

        //            if (iResult < 0) break;
        //        }

        //    }
        //    catch (Exception ex)
        //    {
        //        errorinfo = ex.ToString();
        //        iResult = -1;
        //    }
        //    return iResult;
        //}
    }

    public class ActionListFirstPblock   //与设置的不同,不能直接继承
    {
        public static string Request(List<CosemObject> OIList, ref string errorinfo)
        {
            string FormatValue = string.Empty;
            try
            {
                foreach (CosemObject OI in OIList)
                {
                    FormatValue += CAD.GetFormatValue(OI, ref errorinfo);
                }
                FormatValue = BERiLen.GetFormatValue(OIList.Count) + FormatValue;
                FormatValue += DataBlockSA.GetFormatValue(OIList[0].DataNode, ref errorinfo);
                return FormatValue;
            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                return string.Empty;
            }
        }

        public static string Request(List<CosemObject> OIList, ref string BlockData, int DataLen, ref string errorinfo)
        {
            string FormatValue = string.Empty;
            try
            {
                foreach (CosemObject OI in OIList)
                {
                    FormatValue += CAD.GetFormatValue(OI, ref errorinfo);
                }
                FormatValue = BERiLen.GetFormatValue(OIList.Count) + FormatValue;

                int SDataLen = DataLen - FormatValue.Length;
                FormatValue += DataBlockSA.GetFormatValue(BlockData, ref SDataLen, 1, ref errorinfo);
                BlockData = BlockData.Substring(SDataLen);

                //string mblockData = BlockData.Substring(0, DataLen * 2 - FormatValue.Length);

                //FormatValue += DataBlockSA.GetFormatValue(mblockData, 1, false, ref errorinfo);
                //BlockData = BlockData.Substring(mblockData.Length);


            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
            }
            return FormatValue;
        }

        public static int Response(ref string frameData, List<CosemObject> OIList, ref string errorinfo)
        {
            int iresult = 0;
            return iresult;
        }
    }

    public class ActionPblock : SetDatablock
    {
        //public static string Request(CosemObject OI, double frameseq, bool finished,ref string errorinfo)
        //{
        //    return DataBlockSA.GetFormatValue(OI.DataNode.FrameValue, frameseq,finished,ref errorinfo );
          
        //}

        public static int Response(ref string frameData, CosemObject OI, ref long frameseq, ref bool finished,ref string RawData, ref string errorinfo)
        {
            int iResult = -1;
            if (string.IsNullOrEmpty(frameData))
            {
                errorinfo = "解析数据为空";
                return iResult;
            }
            try
            {
                iResult = DataBlockSA.AnalizeData(ref frameData, OI.DataNode, ref frameseq, ref finished,ref RawData, ref errorinfo);

            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                iResult = -1;
            }
            return iResult;
        }
    }

    public class ACSE_Action 
    {
       // static string m_piid = "81";   //服务序号-优先级     PIID

        public static string Request(List<CosemObject> OIList, string rwtype,double frameseq,bool finished, ref string errorinfo)
        {
            string FormatValue = string.Empty;

            ActionRRMode setMode = (ActionRRMode)Enum.Parse(typeof(ActionRRMode), rwtype);
            switch (setMode)
            {
                case ActionRRMode.ActionNormal:
                    FormatValue = ActionNormal.Request(OIList[0],  ref errorinfo);
                    break;
                case ActionRRMode.ActionList:
                    FormatValue = ActionList.Request(OIList, ref errorinfo);
                    break;
                case ActionRRMode.ActionFirstPblock:
                    FormatValue = ActionFirstPblock.Request(OIList[0], ref errorinfo);
                    break;
                case ActionRRMode.ActionListFirstPblock:
                    FormatValue = ActionListFirstPblock.Request(OIList, ref errorinfo);
                    break;
                case ActionRRMode.ActionNextPblock:
                    FormatValue = ActionNextPblock.Request(frameseq);
                    break;
                case ActionRRMode.ActionPblock:
                    FormatValue = ActionPblock.Request(OIList[0],ref errorinfo);
                    break;

            }
            return  FormatValue;
            //return MyConvert.DecToHex(((int)ClientApduSel.ActionRequest).ToString(), 2) + MyConvert.DecToHex(((int)setMode).ToString(), 2) + m_piid + FormatValue;
        }

        public static int Response(ref string frameData, List<CosemObject> OIList, ref long frameseq, ref bool finished, ref string RawData, ref string errorinfo)
        {
            int iResult = -1;
            try
            {
                if (string.IsNullOrEmpty(frameData))
                {
                    errorinfo = "解析数据为空";
                    return -1;
                }

                ActionREMode getMode = (ActionREMode)Enum.Parse(typeof(ActionREMode), frameData.Substring(0, 2));
                string piid = frameData.Substring(2, 2);

                frameData = frameData.Substring(4); //去掉前面的回应类标志、PIID

                switch (getMode)
                {
                    case ActionREMode.ActionNormal:
                        //只一个OMD
                        iResult = ActionNormal.Response(ref frameData, OIList[0],  ref  errorinfo);
                        break;
                    case ActionREMode.ActionList:
                        //包含多个OMD
                        iResult = ActionList.Response(ref frameData, OIList, ref  errorinfo);
                        break;                   
                    case ActionREMode.ActionNextPblock:
                        iResult = ActionNextPblock.Response(ref frameData, ref frameseq,ref  errorinfo);
                        break;
                    case ActionREMode.ActionPblock:
                        iResult = ActionPblock.Response(ref frameData, OIList[0], ref frameseq,ref finished,ref RawData, ref  errorinfo);
                        break;
                }

            }
            catch (Exception ex)
            {
                errorinfo = ex.ToString();
                iResult = -1;
            }
            return iResult;

        }
    }

   
}
